# -*- coding: utf-8 -*-
import os
import json
import random
import requests
import nest_asyncio

from uuid import getnode as get_mac
from abc import ABCMeta, abstractmethod
from robot import logging, config, utils
from robot.sdk import unit
from EdgeGPT import Chatbot as EdgeChatbot, ConversationStyle
import re
import asyncio

logger = logging.getLogger(__name__)


class AbstractRobot(object):

    __metaclass__ = ABCMeta

    @classmethod
    def get_instance(cls):
        profile = cls.get_config()
        instance = cls(**profile)
        return instance

    def __init__(self, **kwargs):
        pass

    @abstractmethod
    def chat(self, texts, parsed):
        pass

    @abstractmethod
    def stream_chat(self, texts):
        pass


class TulingRobot(AbstractRobot):

    SLUG = "tuling"

    def __init__(self, tuling_key):
        """
        图灵机器人
        """
        super(self.__class__, self).__init__()
        self.tuling_key = tuling_key

    @classmethod
    def get_config(cls):
        return config.get("tuling", {})

    def chat(self, texts, parsed=None):
        """
        使用图灵机器人聊天

        Arguments:
        texts -- user input, typically speech, to be parsed by a module
        """
        msg = "".join(texts)
        msg = utils.stripPunctuation(msg)
        try:
            url = "http://openapi.turingapi.com/openapi/api/v2"
            userid = str(get_mac())[:32]
            body = {
                "perception": {"inputText": {"text": msg}},
                "userInfo": {"apiKey": self.tuling_key, "userId": userid},
            }
            r = requests.post(url, json=body)
            respond = json.loads(r.text)
            result = ""
            if "results" in respond:
                for res in respond["results"]:
                    result += "\n".join(res["values"].values())
            else:
                result = "图灵机器人服务异常，请联系作者"
            logger.info(f"{self.SLUG} 回答：{result}")
            return result
        except Exception:
            logger.critical(
                "Tuling robot failed to response for %r", msg, exc_info=True
            )
            return "抱歉, 图灵机器人服务回答失败"


class UnitRobot(AbstractRobot):

    SLUG = "unit"

    def __init__(self):
        """
        百度UNIT机器人
        """
        super(self.__class__, self).__init__()

    @classmethod
    def get_config(cls):
        return {}

    def chat(self, texts, parsed):
        """
        使用百度UNIT机器人聊天

        Arguments:
        texts -- user input, typically speech, to be parsed by a module
        """
        msg = "".join(texts)
        msg = utils.stripPunctuation(msg)
        try:
            result = unit.getSay(parsed)
            logger.info("{} 回答：{}".format(self.SLUG, result))
            return result
        except Exception:
            logger.critical("UNIT robot failed to response for %r", msg, exc_info=True)
            return "抱歉, 百度UNIT服务回答失败"


class AnyQRobot(AbstractRobot):

    SLUG = "anyq"

    def __init__(self, host, port, solr_port, threshold, secondary):
        """
        AnyQ机器人
        """
        super(self.__class__, self).__init__()
        self.host = host
        self.threshold = threshold
        self.port = port
        self.secondary = secondary

    @classmethod
    def get_config(cls):
        # Try to get anyq config from config
        return config.get("anyq", {})

    def chat(self, texts, parsed):
        """
        使用AnyQ机器人聊天

        Arguments:
        texts -- user input, typically speech, to be parsed by a module
        """
        msg = "".join(texts)
        msg = utils.stripPunctuation(msg)
        try:
            url = f"http://{self.host}:{self.port}/anyq?question={msg}"
            r = requests.get(url)
            respond = json.loads(r.text)
            logger.info(f"anyq response: {respond}")
            if len(respond) > 0:
                # 有命中，进一步判断 confidence 是否达到要求
                confidence = respond[0]["confidence"]
                if confidence >= self.threshold:
                    # 命中该问题，返回回答
                    answer = respond[0]["answer"]
                    if utils.validjson(answer):
                        answer = random.choice(json.loads(answer))
                    logger.info(f"{self.SLUG} 回答：{answer}")
                    return answer
            # 没有命中，走兜底
            if self.secondary != "null" and self.secondary:
                try:
                    ai = get_robot_by_slug(self.secondary)
                    return ai.chat(texts, parsed)
                except Exception:
                    logger.critical(
                        f"Secondary robot {self.secondary} failed to response for {msg}"
                    )
                    return get_unknown_response()
            else:
                return get_unknown_response()
        except Exception:
            logger.critical("AnyQ robot failed to response for %r", msg, exc_info=True)
            return "抱歉, AnyQ回答失败"

# class NewBingAIRobot(AbstractRobot):
#     SLUG = "newbing"
#     cookieData = None
#     count: int = 0

#     conversation_style: ConversationStyle = None
#     bot: EdgeChatbot
#     def __init__(
#         self, 
#         session_id: str = "unknown", 
#         conversation_style: ConversationStyle = ConversationStyle.creative
#     ):
#         """
#         newbing机器人
#         """
#         self.session_id = session_id
#         self.conversation_style = conversation_style
#         # self.cookieData = []
#         self.cookieData = json.loads('[{"domain":".bing.com","expirationDate":1713840948.87633,"hostOnly":false,"httpOnly":false,"name":"SnrOvr","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"X=rebateson"},{"domain":".bing.com","expirationDate":1716778253.779695,"hostOnly":false,"httpOnly":false,"name":"SRCHUSR","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"DOB=20230408&T=1682218251000&POEX=W"},{"domain":".bing.com","expirationDate":1682261453.46743,"hostOnly":false,"httpOnly":true,"name":"SUID","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"A"},{"domain":".bing.com","expirationDate":1716778547.695469,"hostOnly":false,"httpOnly":false,"name":"SRCHHPGUSR","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"SRCHLANG=zh-Hans&DM=1&WTS=63816885668&PV=10.0.0&BRW=XW&BRH=M&CW=1863&CH=969&SCW=1863&SCH=969&DPR=1.0&UTC=480&EXLTT=14&HV=1682218548&PRVCW=945&PRVCH=1020&THEME=1"},{"domain":".bing.com","expirationDate":1716778522.468782,"hostOnly":false,"httpOnly":false,"name":"ANON","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"A=D4639926A6E39235A3C69CD7FFFFFFFF&E=1c35&W=1"},{"domain":".bing.com","expirationDate":1682304948,"hostOnly":false,"httpOnly":false,"name":"_clsk","path":"/","sameSite":null,"secure":false,"session":false,"storeId":null,"value":"1fd8trk|1682218548434|2|1|q.clarity.ms/collect"},{"domain":".bing.com","hostOnly":false,"httpOnly":false,"name":"_SS","path":"/","sameSite":"no_restriction","secure":true,"session":true,"storeId":null,"value":"SID=0E476E8BBD326CB6284A7C77BC1C6D66&R=230&RB=230&GB=0&RG=0&RP=230"},{"domain":".bing.com","hostOnly":false,"httpOnly":false,"name":"ipv6","path":"/","sameSite":"no_restriction","secure":true,"session":true,"storeId":null,"value":"hit=1682221853886&t=4"},{"domain":".bing.com","expirationDate":1683428122.46876,"hostOnly":false,"httpOnly":false,"name":"_U","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"1qcpf5-BEUD3DNV8AdKk95lvG-3ZQ5Jo0ldLyVkVG9yA1h95feJp8-cFSeL9EPloXWblVDGvZdDSuUx7aUKAcv-zkkwP0wGP4WiiIwZ_tzg3CL97Bd9h8trXuArsWFyTyY2o2xNu5YeeZ6OqRkLseTNy3ifLJU_ZFbLY2pwpvDrZSnKXyEB_2hKpYKEzxK1MiE1oDNXRRJNvc5Zt_Nnjxrg"},{"domain":".bing.com","expirationDate":1715488154.638288,"hostOnly":false,"httpOnly":false,"name":"SRCHD","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"AF=SHORUN"},{"domain":".bing.com","expirationDate":1715848912.290174,"hostOnly":false,"httpOnly":false,"name":"PPLState","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"1"},{"domain":".bing.com","expirationDate":1683541573,"hostOnly":false,"httpOnly":false,"name":"ANIMIA","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"FRE=1"},{"domain":".bing.com","expirationDate":1714624154.638245,"hostOnly":false,"httpOnly":true,"name":"_EDGE_V","path":"/","sameSite":null,"secure":false,"session":false,"storeId":null,"value":"1"},{"domain":".bing.com","expirationDate":1698594112.29014,"hostOnly":false,"httpOnly":false,"name":"NAP","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"V=1.9&E=1bdb&C=AjZ0xfyak-JeEIxZ2-CDS19D8ypUy_cGTs9cAooKcinSxgJSPCsm0Q&W=1"},{"domain":".bing.com","expirationDate":1713840948.876253,"hostOnly":false,"httpOnly":false,"name":"_RwBf","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"ilt=12&ihpd=0&ispd=1&rc=230&rb=230&gb=0&rg=0&pc=230&mtu=0&rbb=0.0&g=0&cid=&clo=0&v=3&l=2023-04-22T07:00:00.0000000Z&lft=0001-01-01T00:00:00.0000000&aof=0&o=0&p=bingcopilotwaitlist&c=MY00IA&t=9177&s=2023-03-02T03:01:54.0862758+00:00&ts=2023-04-23T02:55:47.1981689+00:00&rwred=0&wls=2&lka=0&lkt=0&TH=&r=1&mta=0&e=LTAID-bkkrNKPOyxwlkbXs4n1uIBo8ryiylsBAAaP9WL3w71O7jFMShGT5G_EXl2mdoWTOJiEqdB6Cr6R-Wy66zWKbvbzA4L56Z43W9RqmE&A="},{"domain":".bing.com","expirationDate":1716778253.381912,"hostOnly":false,"httpOnly":false,"name":"_UR","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"QS=0&TQS=0"},{"domain":".bing.com","hostOnly":false,"httpOnly":true,"name":"_EDGE_S","path":"/","sameSite":null,"secure":false,"session":true,"storeId":null,"value":"SID=0E476E8BBD326CB6284A7C77BC1C6D66"},{"domain":"www.bing.com","expirationDate":1715914548.29128,"hostOnly":true,"httpOnly":true,"name":"MUIDB","path":"/","sameSite":null,"secure":false,"session":false,"storeId":null,"value":"31B80DDB31E364B723E61F3630856560"},{"domain":".bing.com","expirationDate":1715848876.456891,"hostOnly":false,"httpOnly":true,"name":"USRLOC","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"HS=1&ELOC=LAT=32.792816162109375|LON=-96.82738494873047|N=%E8%BE%BE%E6%8B%89%E6%96%AF%EF%BC%8C%E5%BE%B7%E5%B7%9E|ELT=1|"},{"domain":".bing.com","expirationDate":1713754293,"hostOnly":false,"httpOnly":false,"name":"_clck","path":"/","sameSite":null,"secure":false,"session":false,"storeId":null,"value":"1rmikz8|1|fb0|0"},{"domain":".bing.com","expirationDate":1716778253.475161,"hostOnly":false,"httpOnly":false,"name":"_HPVN","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"CS=eyJQbiI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiUCJ9LCJTYyI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiSCJ9LCJReiI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiVCJ9LCJBcCI6dHJ1ZSwiTXV0ZSI6dHJ1ZSwiTGFkIjoiMjAyMy0wNC0yM1QwMDowMDowMFoiLCJJb3RkIjowLCJHd2IiOjAsIkRmdCI6bnVsbCwiTXZzIjowLCJGbHQiOjAsIkltcCI6Mn0="},{"domain":".bing.com","expirationDate":1715515158.449725,"hostOnly":false,"httpOnly":false,"name":"ABDEF","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"V=13&ABDV=11&MRNB=1680955158448&MRB=0"},{"domain":".bing.com","expirationDate":1715848912.290204,"hostOnly":false,"httpOnly":true,"name":"KievRPSSecAuth","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"FABaBBRaTOJILtFsMkpLVWSG6AN6C/svRwNmAAAEgAAACJO/YbKW9xGnGAQdaTMHV0tk3DCIyTstvhEzwvT8S8FZsFh/dDz2OTSSLeuHQ8Q2RLLTxPu7BqMPGGbvh74DiPRRl80e3vW6GZTdaMtwxK1A+A9jkXr7DTTCSZyKsjuPuHQO00DaDzsjMUkrTPpwHRkWHf26Z62z8kYXVJxT7J+qfyOfuoeXtCDY5DF6+Vtu9mM/Mb+FUsgMepVPLuBjFJca0hgpM/YK+RK0xDRjBSk0uCdHCM/gslypCjfkBeJgHsftLKQvbznKxMndDwHQlRUBZmyuX/laokvE3ABPH8DcALMgDfVXIHJYSIP6hb79JIhCRAYLmIP4/qsIOSkX3S80efTgZr4X0jHZSKRIEe/8fQA4i8KcOvJyzUhD2p+S5GUH+Q3Dm6E6qv1V2VcJ6FbYn//iLSn9cLN8ezxVNxKOV8TeA7rTZKM8fecl0jI4SBVYJ0HQVtcI7yTtOUtZ20AEu43xVyEFRKgB+ImUMAF7Y6ZEFbp/tiKa7mXdiNJFZGfLgZKyJbXYEDzpz14BAjWzIzeAWiBI1+eL43m3n0A2M8PN1Yhon8UcwqK+e7NHNUV0RU1v5vgJbUs9dtDD+uckmLVfi7e2tCvWoB+JN8th0TLgjglCXiV3anZs/RwvrdM9LnkBczyeE5uk21Q1P8SiFzEDObjpS3kZom31n7gJ2rFHmwlWpmMXeu/X6HnIPwXLP/sUCDRUqrhd/uboe9WC1GJIetc8A072WRYEf5AhlZUEuaph3oZlsRw0pwf3H5BkfQ2oYmb2K7mCvceX1pXvgwyw5No5nR588Kvjc95lJg822ybKsDCYuo0sRrgQwd6ZwrkzIE8RWmhskSFnU+hpI3uSW6HM//d9uA86Uv46WsLzH4YhQKflex0xrnJ2a2PD2n7oNJgorlTfh+v1ukBNi3ao5jDcEup2OC7AU4UCA9KY12AHigVPN1JDrsS+ZbhmrTuP7tJiT4+9FDlu/r0O9Y6GydGpYsPV0LiQWDefdJIA7qNps7OvvX8QDL+XfV2Tnftg6E8lygpAR52gT/n89bcU9tt37MDd0lEnjz93P9Jypsk8Sah+Gid4EXf8Fs2jisOVvImcgGJGoxjVcFct6wHqFMcnGUBEaf7aPnmxTm6dymQfHHhqvqCg52SG/KqdMYjNHU0KcSCYjuf5fcs6EjtgdYWOYNI0E03GKHXmR7ehWTSOIV2qT4G3lhYdxwW0NAjH9RvIY/eojA6wzqS0vBRkGIyxoWLR7ah8bzoIAWYORCGB8efGamitP1c4eddVCxsgXLI1EdfRuBij+bgrDVob1+KYmmShaPRGjz3TsQzQzbd4FLeoA3m7DamI/IBUuzG4zHxaJbkvGeQczXp6XuAKDEikf6TXay8MtXlOQivd6GZcb1VTPEhrmhQDVDsiFABBhqZ5rNdwi5K3ifDReI9hz//cvg=="},{"domain":".bing.com","expirationDate":1715914223.725469,"hostOnly":false,"httpOnly":false,"name":"MUID","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"31B80DDB31E364B723E61F3630856560"},{"domain":".bing.com","hostOnly":false,"httpOnly":false,"name":"SNRHOP","path":"/","sameSite":"no_restriction","secure":true,"session":true,"storeId":null,"value":"I=&TS="},{"domain":".bing.com","expirationDate":1715488154.638308,"hostOnly":false,"httpOnly":false,"name":"SRCHUID","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"V=2&GUID=A999EB6316DA44B7A26269C77E8A0E0B&dmnchg=1"},{"domain":".bing.com","expirationDate":1682498512.70634,"hostOnly":false,"httpOnly":true,"name":"WLID","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"7iAGydP0BmukOZ4gN3fSycWmst5KoIEfZllOgxvHTvzAIm7dPOBmviiEGWIm2Lh67cT04MVRJlBZvnugvlM8AqXqjAl4CqOTxCFJl27jtpE="},{"domain":".bing.com","hostOnly":false,"httpOnly":false,"name":"WLS","path":"/","sameSite":"no_restriction","secure":true,"session":true,"storeId":null,"value":"C=3a773f3b7380ebea&N=Lin"}]')
#         # self.cookieData = self.get_config().config.get("cookie")
#         self.bot = EdgeChatbot(cookies=self.cookieData, proxy=None)
#     @classmethod
#     def get_config(cls):
#         # Try to get anyq config from config
#         return config.get("newbing", {})
#     async def stream_chat(self, texts):
#         logger.info('speak: ' + texts)
#         self.count = self.count + 1
#         parsed_content = ''
#         """
#         使用Newbing机器人聊天
#         """
#         msg = "".join(texts)
#         logger.info('msg: ' + msg)
#         result = await self.bot.ask(prompt=msg,wss_link="wss://sydney.bing.com/sydney/ChatHub",conversation_style=self.conversation_style)
#         result = "test"
#         logger.info(result)
#         return result

class NewBingAIRobot(AbstractRobot):
    SLUG = "newbing"
    cookieData = None
    count: int = 0

    conversation_style: ConversationStyle = None
    bot: EdgeChatbot
    def __init__(
        self, 
        session_id: str = "unknown", 
        conversation_style: ConversationStyle = ConversationStyle.creative
    ):
        """
        newbing机器人
        """
        logger.info('newbing init begin...')
        self.session_id = session_id
        self.conversation_style = conversation_style
        # self.cookieData = []
        self.cookieData = json.loads('[{"domain":".bing.com","expirationDate":1713840948.87633,"hostOnly":false,"httpOnly":false,"name":"SnrOvr","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"X=rebateson"},{"domain":".bing.com","expirationDate":1716778253.779695,"hostOnly":false,"httpOnly":false,"name":"SRCHUSR","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"DOB=20230408&T=1682218251000&POEX=W"},{"domain":".bing.com","expirationDate":1682261453.46743,"hostOnly":false,"httpOnly":true,"name":"SUID","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"A"},{"domain":".bing.com","expirationDate":1716778547.695469,"hostOnly":false,"httpOnly":false,"name":"SRCHHPGUSR","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"SRCHLANG=zh-Hans&DM=1&WTS=63816885668&PV=10.0.0&BRW=XW&BRH=M&CW=1863&CH=969&SCW=1863&SCH=969&DPR=1.0&UTC=480&EXLTT=14&HV=1682218548&PRVCW=945&PRVCH=1020&THEME=1"},{"domain":".bing.com","expirationDate":1716778522.468782,"hostOnly":false,"httpOnly":false,"name":"ANON","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"A=D4639926A6E39235A3C69CD7FFFFFFFF&E=1c35&W=1"},{"domain":".bing.com","expirationDate":1682304948,"hostOnly":false,"httpOnly":false,"name":"_clsk","path":"/","sameSite":null,"secure":false,"session":false,"storeId":null,"value":"1fd8trk|1682218548434|2|1|q.clarity.ms/collect"},{"domain":".bing.com","hostOnly":false,"httpOnly":false,"name":"_SS","path":"/","sameSite":"no_restriction","secure":true,"session":true,"storeId":null,"value":"SID=0E476E8BBD326CB6284A7C77BC1C6D66&R=230&RB=230&GB=0&RG=0&RP=230"},{"domain":".bing.com","hostOnly":false,"httpOnly":false,"name":"ipv6","path":"/","sameSite":"no_restriction","secure":true,"session":true,"storeId":null,"value":"hit=1682221853886&t=4"},{"domain":".bing.com","expirationDate":1683428122.46876,"hostOnly":false,"httpOnly":false,"name":"_U","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"1qcpf5-BEUD3DNV8AdKk95lvG-3ZQ5Jo0ldLyVkVG9yA1h95feJp8-cFSeL9EPloXWblVDGvZdDSuUx7aUKAcv-zkkwP0wGP4WiiIwZ_tzg3CL97Bd9h8trXuArsWFyTyY2o2xNu5YeeZ6OqRkLseTNy3ifLJU_ZFbLY2pwpvDrZSnKXyEB_2hKpYKEzxK1MiE1oDNXRRJNvc5Zt_Nnjxrg"},{"domain":".bing.com","expirationDate":1715488154.638288,"hostOnly":false,"httpOnly":false,"name":"SRCHD","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"AF=SHORUN"},{"domain":".bing.com","expirationDate":1715848912.290174,"hostOnly":false,"httpOnly":false,"name":"PPLState","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"1"},{"domain":".bing.com","expirationDate":1683541573,"hostOnly":false,"httpOnly":false,"name":"ANIMIA","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"FRE=1"},{"domain":".bing.com","expirationDate":1714624154.638245,"hostOnly":false,"httpOnly":true,"name":"_EDGE_V","path":"/","sameSite":null,"secure":false,"session":false,"storeId":null,"value":"1"},{"domain":".bing.com","expirationDate":1698594112.29014,"hostOnly":false,"httpOnly":false,"name":"NAP","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"V=1.9&E=1bdb&C=AjZ0xfyak-JeEIxZ2-CDS19D8ypUy_cGTs9cAooKcinSxgJSPCsm0Q&W=1"},{"domain":".bing.com","expirationDate":1713840948.876253,"hostOnly":false,"httpOnly":false,"name":"_RwBf","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"ilt=12&ihpd=0&ispd=1&rc=230&rb=230&gb=0&rg=0&pc=230&mtu=0&rbb=0.0&g=0&cid=&clo=0&v=3&l=2023-04-22T07:00:00.0000000Z&lft=0001-01-01T00:00:00.0000000&aof=0&o=0&p=bingcopilotwaitlist&c=MY00IA&t=9177&s=2023-03-02T03:01:54.0862758+00:00&ts=2023-04-23T02:55:47.1981689+00:00&rwred=0&wls=2&lka=0&lkt=0&TH=&r=1&mta=0&e=LTAID-bkkrNKPOyxwlkbXs4n1uIBo8ryiylsBAAaP9WL3w71O7jFMShGT5G_EXl2mdoWTOJiEqdB6Cr6R-Wy66zWKbvbzA4L56Z43W9RqmE&A="},{"domain":".bing.com","expirationDate":1716778253.381912,"hostOnly":false,"httpOnly":false,"name":"_UR","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"QS=0&TQS=0"},{"domain":".bing.com","hostOnly":false,"httpOnly":true,"name":"_EDGE_S","path":"/","sameSite":null,"secure":false,"session":true,"storeId":null,"value":"SID=0E476E8BBD326CB6284A7C77BC1C6D66"},{"domain":"www.bing.com","expirationDate":1715914548.29128,"hostOnly":true,"httpOnly":true,"name":"MUIDB","path":"/","sameSite":null,"secure":false,"session":false,"storeId":null,"value":"31B80DDB31E364B723E61F3630856560"},{"domain":".bing.com","expirationDate":1715848876.456891,"hostOnly":false,"httpOnly":true,"name":"USRLOC","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"HS=1&ELOC=LAT=32.792816162109375|LON=-96.82738494873047|N=%E8%BE%BE%E6%8B%89%E6%96%AF%EF%BC%8C%E5%BE%B7%E5%B7%9E|ELT=1|"},{"domain":".bing.com","expirationDate":1713754293,"hostOnly":false,"httpOnly":false,"name":"_clck","path":"/","sameSite":null,"secure":false,"session":false,"storeId":null,"value":"1rmikz8|1|fb0|0"},{"domain":".bing.com","expirationDate":1716778253.475161,"hostOnly":false,"httpOnly":false,"name":"_HPVN","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"CS=eyJQbiI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiUCJ9LCJTYyI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiSCJ9LCJReiI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiVCJ9LCJBcCI6dHJ1ZSwiTXV0ZSI6dHJ1ZSwiTGFkIjoiMjAyMy0wNC0yM1QwMDowMDowMFoiLCJJb3RkIjowLCJHd2IiOjAsIkRmdCI6bnVsbCwiTXZzIjowLCJGbHQiOjAsIkltcCI6Mn0="},{"domain":".bing.com","expirationDate":1715515158.449725,"hostOnly":false,"httpOnly":false,"name":"ABDEF","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"V=13&ABDV=11&MRNB=1680955158448&MRB=0"},{"domain":".bing.com","expirationDate":1715848912.290204,"hostOnly":false,"httpOnly":true,"name":"KievRPSSecAuth","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"FABaBBRaTOJILtFsMkpLVWSG6AN6C/svRwNmAAAEgAAACJO/YbKW9xGnGAQdaTMHV0tk3DCIyTstvhEzwvT8S8FZsFh/dDz2OTSSLeuHQ8Q2RLLTxPu7BqMPGGbvh74DiPRRl80e3vW6GZTdaMtwxK1A+A9jkXr7DTTCSZyKsjuPuHQO00DaDzsjMUkrTPpwHRkWHf26Z62z8kYXVJxT7J+qfyOfuoeXtCDY5DF6+Vtu9mM/Mb+FUsgMepVPLuBjFJca0hgpM/YK+RK0xDRjBSk0uCdHCM/gslypCjfkBeJgHsftLKQvbznKxMndDwHQlRUBZmyuX/laokvE3ABPH8DcALMgDfVXIHJYSIP6hb79JIhCRAYLmIP4/qsIOSkX3S80efTgZr4X0jHZSKRIEe/8fQA4i8KcOvJyzUhD2p+S5GUH+Q3Dm6E6qv1V2VcJ6FbYn//iLSn9cLN8ezxVNxKOV8TeA7rTZKM8fecl0jI4SBVYJ0HQVtcI7yTtOUtZ20AEu43xVyEFRKgB+ImUMAF7Y6ZEFbp/tiKa7mXdiNJFZGfLgZKyJbXYEDzpz14BAjWzIzeAWiBI1+eL43m3n0A2M8PN1Yhon8UcwqK+e7NHNUV0RU1v5vgJbUs9dtDD+uckmLVfi7e2tCvWoB+JN8th0TLgjglCXiV3anZs/RwvrdM9LnkBczyeE5uk21Q1P8SiFzEDObjpS3kZom31n7gJ2rFHmwlWpmMXeu/X6HnIPwXLP/sUCDRUqrhd/uboe9WC1GJIetc8A072WRYEf5AhlZUEuaph3oZlsRw0pwf3H5BkfQ2oYmb2K7mCvceX1pXvgwyw5No5nR588Kvjc95lJg822ybKsDCYuo0sRrgQwd6ZwrkzIE8RWmhskSFnU+hpI3uSW6HM//d9uA86Uv46WsLzH4YhQKflex0xrnJ2a2PD2n7oNJgorlTfh+v1ukBNi3ao5jDcEup2OC7AU4UCA9KY12AHigVPN1JDrsS+ZbhmrTuP7tJiT4+9FDlu/r0O9Y6GydGpYsPV0LiQWDefdJIA7qNps7OvvX8QDL+XfV2Tnftg6E8lygpAR52gT/n89bcU9tt37MDd0lEnjz93P9Jypsk8Sah+Gid4EXf8Fs2jisOVvImcgGJGoxjVcFct6wHqFMcnGUBEaf7aPnmxTm6dymQfHHhqvqCg52SG/KqdMYjNHU0KcSCYjuf5fcs6EjtgdYWOYNI0E03GKHXmR7ehWTSOIV2qT4G3lhYdxwW0NAjH9RvIY/eojA6wzqS0vBRkGIyxoWLR7ah8bzoIAWYORCGB8efGamitP1c4eddVCxsgXLI1EdfRuBij+bgrDVob1+KYmmShaPRGjz3TsQzQzbd4FLeoA3m7DamI/IBUuzG4zHxaJbkvGeQczXp6XuAKDEikf6TXay8MtXlOQivd6GZcb1VTPEhrmhQDVDsiFABBhqZ5rNdwi5K3ifDReI9hz//cvg=="},{"domain":".bing.com","expirationDate":1715914223.725469,"hostOnly":false,"httpOnly":false,"name":"MUID","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"31B80DDB31E364B723E61F3630856560"},{"domain":".bing.com","hostOnly":false,"httpOnly":false,"name":"SNRHOP","path":"/","sameSite":"no_restriction","secure":true,"session":true,"storeId":null,"value":"I=&TS="},{"domain":".bing.com","expirationDate":1715488154.638308,"hostOnly":false,"httpOnly":false,"name":"SRCHUID","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"V=2&GUID=A999EB6316DA44B7A26269C77E8A0E0B&dmnchg=1"},{"domain":".bing.com","expirationDate":1682498512.70634,"hostOnly":false,"httpOnly":true,"name":"WLID","path":"/","sameSite":"no_restriction","secure":true,"session":false,"storeId":null,"value":"7iAGydP0BmukOZ4gN3fSycWmst5KoIEfZllOgxvHTvzAIm7dPOBmviiEGWIm2Lh67cT04MVRJlBZvnugvlM8AqXqjAl4CqOTxCFJl27jtpE="},{"domain":".bing.com","hostOnly":false,"httpOnly":false,"name":"WLS","path":"/","sameSite":"no_restriction","secure":true,"session":true,"storeId":null,"value":"C=3a773f3b7380ebea&N=Lin"}]')
        # self.cookieData = self.get_config().config.get("cookie")
        logger.info('newbing init doing...')
        self.bot = EdgeChatbot(cookies=self.cookieData, proxy=None)
        logger.info('newbing init end...')
    @classmethod
    def get_config(cls):
        # Try to get anyq config from config
        return config.get("newbing", {})
    
    @abstractmethod
    def chat(self, texts, parsed):
        self.count = self.count + 1
        msg = "".join(texts)
        logger.info('new bing request..')
        nest_asyncio.apply()
        event_loop = asyncio.get_event_loop()
        r = event_loop.run_until_complete(self.bot.ask(prompt=msg,wss_link="wss://sydney.bing.com/sydney/ChatHub",conversation_style=self.conversation_style))
        # r = await self.bot.ask(prompt=msg,wss_link="wss://sydney.bing.com/sydney/ChatHub",conversation_style=self.conversation_style)
        # r = asyncio.run(self.bot.ask(prompt=msg,wss_link="wss://sydney.bing.com/sydney/ChatHub",conversation_style=self.conversation_style))
        logger.info('new bing return..')
        logger.info(r)
        return r['item']['messages'][1]['text']

class OPENAIRobot(AbstractRobot):

    SLUG = "openai"

    def __init__(
        self,
        openai_api_key,
        model,
        temperature,
        max_tokens,
        top_p,
        frequency_penalty,
        presence_penalty,
        stop_ai,
        prefix="",
        proxy="",
        api_base="",
    ):
        """
        OpenAI机器人
        """
        super(self.__class__, self).__init__()
        self.openai = None
        try:
            import openai

            self.openai = openai
            if not openai_api_key:
                openai_api_key = os.getenv("OPENAI_API_KEY")
            self.openai.api_key = openai_api_key
            if proxy:
                logger.info(f"{self.SLUG} 使用代理：{proxy}")
                self.openai.proxy = proxy

        except Exception:
            logger.critical("OpenAI 初始化失败，请升级 Python 版本至 > 3.6")
        self.model = model
        self.prefix = prefix
        self.temperature = temperature
        self.max_tokens = max_tokens
        self.top_p = top_p
        self.frequency_penalty = frequency_penalty
        self.presence_penalty = presence_penalty
        self.stop_ai = stop_ai
        self.api_base = api_base if api_base else "https://api.openai.com/v1/chat"
        self.context = []

    @classmethod
    def get_config(cls):
        # Try to get anyq config from config
        return config.get("openai", {})

    def stream_chat(self, texts):
        """
        从ChatGPT API获取回复
        :return: 回复
        """

        msg = "".join(texts)
        msg = utils.stripPunctuation(msg)
        msg = self.prefix + msg  # 增加一段前缀
        logger.info("msg: " + msg)
        self.context.append({"role": "user", "content": msg})

        header = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.openai.api_key,
        }

        data = {"model": "gpt-3.5-turbo", "messages": self.context, "stream": True}
        logger.info("开始流式请求")
        url = self.api_base + "/completions"
        # 请求接收流式数据
        try:
            response = requests.request(
                "POST",
                url,
                headers=header,
                json=data,
                stream=True,
                proxies={"https": self.openai.proxy},
            )

            def generate():
                stream_content = str()
                one_message = {"role": "assistant", "content": stream_content}
                self.context.append(one_message)
                i = 0
                for line in response.iter_lines():
                    line_str = str(line, encoding="utf-8")
                    if line_str.startswith("data:") and line_str[5:]:
                        if line_str.startswith("data: [DONE]"):
                            break
                        line_json = json.loads(line_str[5:])
                        if "choices" in line_json:
                            if len(line_json["choices"]) > 0:
                                choice = line_json["choices"][0]
                                if "delta" in choice:
                                    delta = choice["delta"]
                                    if "role" in delta:
                                        role = delta["role"]
                                    elif "content" in delta:
                                        delta_content = delta["content"]
                                        i += 1
                                        if i < 40:
                                            logger.debug(delta_content, end="")
                                        elif i == 40:
                                            logger.debug("......")
                                        one_message["content"] = (
                                            one_message["content"] + delta_content
                                        )
                                        yield delta_content

                    elif len(line_str.strip()) > 0:
                        logger.debug(line_str)
                        yield line_str

        except Exception as e:
            ee = e

            def generate():
                yield "request error:\n" + str(ee)

        return generate

    def chat(self, texts, parsed):
        """
        使用OpenAI机器人聊天

        Arguments:
        texts -- user input, typically speech, to be parsed by a module
        """
        msg = "".join(texts)
        msg = utils.stripPunctuation(msg)
        msg = self.prefix + msg  # 增加一段前缀
        logger.info("msg: " + msg)
        try:
            respond = ""
            self.context.append({"role": "user", "content": msg})
            response = self.openai.Completion.create(
                model=self.model,
                messages=self.context,
                temperature=self.temperature,
                max_tokens=self.max_tokens,
                top_p=self.top_p,
                frequency_penalty=self.frequency_penalty,
                presence_penalty=self.presence_penalty,
                stop=self.stop_ai,
                api_base=self.api_base
            )
            message = response.choices[0].message
            respond = message.content
            self.context.append(message)
            return respond
        except self.openai.error.InvalidRequestError:
            logger.warning("token超出长度限制，丢弃历史会话")
            self.context = []
            return self.chat(texts, parsed)
        except Exception:
            logger.critical(
                "openai robot failed to response for %r", msg, exc_info=True
            )
            return "抱歉，OpenAI 回答失败"


def get_unknown_response():
    """
    不知道怎么回答的情况下的答复

    :returns: 表示不知道的答复
    """
    results = ["抱歉，我不会这个呢", "我不会这个呢", "我还不会这个呢", "我还没学会这个呢", "对不起，你说的这个，我还不会"]
    return random.choice(results)


def get_robot_by_slug(slug):
    """
    Returns:
        A robot implementation available on the current platform
    """
    if not slug or type(slug) is not str:
        raise TypeError("Invalid slug '%s'", slug)

    selected_robots = list(
        filter(
            lambda robot: hasattr(robot, "SLUG") and robot.SLUG == slug, get_robots()
        )
    )
    if len(selected_robots) == 0:
        raise ValueError("No robot found for slug '%s'" % slug)
    else:
        if len(selected_robots) > 1:
            logger.warning(
                "WARNING: Multiple robots found for slug '%s'. "
                + "This is most certainly a bug." % slug
            )
        robot = selected_robots[0]
        logger.info(f"使用 {robot.SLUG} 对话机器人")
        return robot.get_instance()


def get_robots():
    def get_subclasses(cls):
        subclasses = set()
        for subclass in cls.__subclasses__():
            subclasses.add(subclass)
            subclasses.update(get_subclasses(subclass))
        return subclasses

    return [
        robot
        for robot in list(get_subclasses(AbstractRobot))
        if hasattr(robot, "SLUG") and robot.SLUG
    ]
